<!-- HTML header for doxygen 1.8.13-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Taskflow Handbook</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  $(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname"><a href="https://taskflow.github.io/">Taskflow</a>
   &#160;<span id="projectnumber">3.0.0-Master-Branch</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.14 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('A2ReduceCPU.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Parallel Reduction </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Taskflow provides template function that constructs a task to perform parallel reduction over a range of items.</p>
<h1><a class="anchor" id="A2ParallelReduction"></a>
Parallel Reduction</h1>
<p>The reduction task created by <a class="el" href="classtf_1_1FlowBuilder.html#ad999cd75045db225a42d5881d6db1223" title="constructs a STL-styled parallel-reduce task ">tf::Taskflow::reduce(B&amp;&amp; first, E&amp;&amp; last, T&amp; result, O&amp;&amp; bop)</a> performs parallel reduction over a range of elements specified by <code>[beg, end)</code> using the binary operator <code>bop</code> and stores the reduced result in <code>result</code>. It represents the parallel execution of the following reduction loop:</p>
<div class="fragment"><div class="line"><span class="keywordflow">for</span>(<span class="keyword">auto</span> itr=first; itr&lt;last; itr++) {</div><div class="line">  result = bop(result, *itr);</div><div class="line">}</div></div><!-- fragment --><p>At runtime, the reduction task spawns a subflow to perform parallel reduction. The reduced result is stored in <code>result</code> that will be captured by reference in the reduction task. It is your responsibility to ensure <code>result</code> remains alive during the parallel execution.</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> sum = 100;</div><div class="line"><a class="codeRef" doxygen="/Users/twhuang/PhD/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector&lt;int&gt;</a> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};</div><div class="line"></div><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> task = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#ad999cd75045db225a42d5881d6db1223">reduce</a>(vec.begin(), vec.end(), sum, [] (<span class="keywordtype">int</span> l, <span class="keywordtype">int</span> r) { </div><div class="line">  <span class="keywordflow">return</span> l + r;    <span class="comment">// binary reducer operator</span></div><div class="line">});</div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow).wait();</div><div class="line"></div><div class="line">assert(sum == 100 + 55);</div></div><!-- fragment --><p>The order in which the binary operator is applied to pairs of elements is <em>unspecified</em>. In other words, the elements of the range may be grouped and rearranged in arbitrary order. The result and the argument types of the binary operator must be consistent with the input data type .</p>
<p>Similar to A1ForEach, you may leverage <a class="elRef" doxygen="/Users/twhuang/PhD/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper.html">std::reference_wrapper</a> to enable stateful parameter passing between tasks for expressing end-to-end parallelism.</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> sum = 100;</div><div class="line"><a class="codeRef" doxygen="/Users/twhuang/PhD/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector&lt;int&gt;</a> vec;</div><div class="line"><a class="codeRef" doxygen="/Users/twhuang/PhD/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector&lt;int&gt;::iterator</a> first, last;</div><div class="line"></div><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> init = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a60d7a666cab71ecfa3010b2efb0d6b57">emplace</a>([&amp;](){</div><div class="line">  vec   = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};</div><div class="line">  first = vec.begin();</div><div class="line">  last  = vec.end();</div><div class="line">});</div><div class="line"></div><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> task = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#ad999cd75045db225a42d5881d6db1223">reduce</a>(std::ref(first), std::ref(last), sum, [] (<span class="keywordtype">int</span> l, <span class="keywordtype">int</span> r) { </div><div class="line">  <span class="keywordflow">return</span> l + r;    <span class="comment">// binary reducer operator</span></div><div class="line">});</div><div class="line"></div><div class="line"><span class="comment">// wrong! must use std::ref, or first and last are captured by copy</span></div><div class="line"><span class="comment">// tf::Task task = taskflow.reduce(first, last, sum, [] (int l, int r) { </span></div><div class="line"><span class="comment">//   return l + r;    // binary reducer operator</span></div><div class="line"><span class="comment">// });</span></div><div class="line"></div><div class="line">init.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(task);</div><div class="line"></div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow).wait();</div><div class="line"></div><div class="line">assert(sum == 100 + 55);</div></div><!-- fragment --><p>In the above example, when <code>init</code> finishes, <code>vec</code> has been initialized to 10 elements with <code>first</code> pointing to the first element and <code>last</code> pointing to the next of the last element (i.e., end of the range). These changes are visible to the execution context of the reduction task.</p>
<h1><a class="anchor" id="A2ParallelTransformationReduction"></a>
Parallel Transformation-Reduction</h1>
<p>It is common to transform each element into a new data type and then perform reduction on the transformed elements. Taskflow provides a method, <a class="el" href="classtf_1_1FlowBuilder.html#ad8d03524f15292610ebee63d53b89579" title="constructs a STL-styled parallel transform-reduce task ">tf::Taskflow::transform_reduce(B&amp;&amp; first, E&amp;&amp; last, T&amp; result, BOP&amp;&amp; bop, UOP&amp;&amp; uop)</a>, that applies <code>uop</code> to transform each element in the specified range and then perform parallel reduction over <code>result</code> and transformed elements. It represents the parallel execution of the following reduction loop:</p>
<div class="fragment"><div class="line"><span class="keywordflow">for</span>(<span class="keyword">auto</span> itr=first; itr&lt;last; itr++) {</div><div class="line">  result = bop(result, uop(*itr));</div><div class="line">}</div></div><!-- fragment --><p>The example below transforms each digit in a string to an integer number and then sums up all integers in parallel.</p>
<div class="fragment"><div class="line"><a class="codeRef" doxygen="/Users/twhuang/PhD/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/string/basic_string.html">std::string</a> str = <span class="stringliteral">&quot;12345678&quot;</span>;</div><div class="line"><span class="keywordtype">int</span> sum {0};</div><div class="line"></div><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> task = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#ad8d03524f15292610ebee63d53b89579">transform_reduce</a>(str.begin(), str.end(), sum,</div><div class="line">  [] (<span class="keywordtype">int</span> a, <span class="keywordtype">int</span> b) {      <span class="comment">// binary reduction operator</span></div><div class="line">    <span class="keywordflow">return</span> a + b;</div><div class="line">  },  </div><div class="line">  [] (<span class="keywordtype">char</span> c) -&gt; <span class="keywordtype">int</span> {     <span class="comment">// unary transformation operator</span></div><div class="line">    <span class="keywordflow">return</span> c - <span class="charliteral">&#39;0&#39;</span>;</div><div class="line">  }   </div><div class="line">); </div><div class="line"></div><div class="line">executor.<a class="code" href="classtf_1_1Executor.html#a81f35d5b0a20ac0646447eb80d97c0aa">run</a>(taskflow).wait(); </div><div class="line"></div><div class="line">assert(sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);  <span class="comment">// sum will be 36 </span></div></div><!-- fragment --><p>The order in which we apply the binary operator on the transformed elements is <em>unspecified</em>. It is possible that the binary operator will take <em>r-value</em> in both arguments, for example, <code>bop(uop(*itr1), uop(*itr2))</code>, due to the transformed temporaries. When data passing is expensive, you may define the result type <code>T</code> to be move-constructible. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.14 </li>
  </ul>
</div>
</body>
</html>
